#ifndef _SPARCV9DECODE_H_
#define _SPARCV9DECODE_H_


#ifdef  __cplusplus
extern "C" {
#endif



        /*
         * Principal instruction decoding for SPARC v9 instruction set.
         * Eventually maybe v8 will be a defined subset of this.
         */


typedef enum {
        illegal_instruction,
        unknown_instruction,
        unknown_fp_instruction,
        bpcc_illegal_cc_specifier,
        bpr_illegal_cc_specifier,
        done_retry_illegal_fcn_field,
        saved_fcn_invalid,
        saved_reserved_field_non_zero,
        tcc_reserved_field_non_zero,
        tcc_illegal_cc_field,
        movcc_reserved_field_non_zero,
        movcc_illegal_cc_field,
        movr_illegal_cc_field,
        odd_rd_for_ldd,
        odd_rd_for_std,
        fpop_bit13_set,
        illegal_fsr_specifier,
        unimplemented_visop,
        illtrap_reserved_field_non_zero,
        fmovcc_reserved_field_non_zero,
        fmovcc_illegal_cc_field,
        flushw_reserved_field_non_zero,
        visop36_reserved_field_non_zero,
        sir_reserved_field_non_zero,
        cas_reserved_field_non_zero
} v9_ill_instn_reason_t;




/*
 * Basic enumeration for the instruction types (op field) opcodes.
 */

typedef enum {
        Ty_0    = 0,    /* Branches and sethi */ /*The SPARC architecture manual defines sethi such that it destroys the least significant ten bits on encoding.*/ 
        Ty_1    = 1,    /* Call               */
        Ty_2    = 2,    /* Arithmetic & Misc  */
        Ty_3    = 3     /* Loads/Stores       */
} ty_code_t;




/*
 * An enumeration table for the op2 values for op==0
 */

typedef enum {
        T0o3_Illtrap = 0,       T0o3_BPcc,
        T0o3_Bicc,              T0o3_BPr,
        T0o3_SetHi,             T0o3_FBPfcc,
        T0o3_FBfcc,             T0o3_unknown_0x7
} T0o3_code_t;

/*
 * An enumeration table for the op3 values for op==2
 */

typedef enum {
    /* Col 0  (0x00 - 0x0f) */
        T2o3_add,       T2o3_and,       T2o3_or,        T2o3_xor,
        T2o3_sub,       T2o3_andn,      T2o3_orn,       T2o3_xnor,
        T2o3_addc,      T2o3_mulx,      T2o3_umul,      T2o3_smul,
        T2o3_subc,      T2o3_udivx,     T2o3_udiv,      T2o3_sdiv,
    /* Col 1  (0x10 - 0x1f) */
        T2o3_addcc,     T2o3_andcc,     T2o3_orcc,      T2o3_xorcc,
        T2o3_subcc,     T2o3_andncc,    T2o3_orncc,     T2o3_xnorcc,
        T2o3_addccc,    T2o3_unknown_0x19, T2o3_umulcc, T2o3_smulcc,
        T2o3_subccc,    T2o3_unknown_0x1d, T2o3_udivcc, T2o3_sdivcc,
    /* Col 2  (0x20 - 0x2f) */
        T2o3_taddcc,    T2o3_tsubcc,    T2o3_taddcctv, T2o3_tsubcctv,
        T2o3_mulscc,    T2o3_sll,       T2o3_srl,       T2o3_sra,
        T2o3_rdasr,     T2o3_rdhpr,     T2o3_rdpr,      T2o3_flushw,
        T2o3_movcc,     T2o3_sdivx,     T2o3_popc,      T2o3_movr,
    /* Col 3  (0x30 - 0x3f) */
        T2o3_wrasr,     T2o3_saved,     T2o3_wrpr,      T2o3_wrhpr,
        T2o3_fpop_0x34, T2o3_fpop_0x35, T2o3_gop,       T2o3_unknown_0x37,
        T2o3_jmpl,      T2o3_return,    T2o3_tcc,       T2o3_flush,
        T2o3_save,      T2o3_restore,   T2o3_retry,     T2o3_unknown_0x3f
} T2o3_code_t;

/*
 * Table of op3 values for the op=3 (load/store) opcodes
 */

typedef enum {
    /* Col 0 (0x00 - 0x0f) */
        T3o3_lduw, T3o3_ldub, T3o3_lduh, T3o3_ldd,
        T3o3_stw, T3o3_stb, T3o3_sth, T3o3_std,
        T3o3_ldsw, T3o3_ldsb, T3o3_ldsh, T3o3_ldx,
        T3o3_unknown_0x0c, T3o3_ldstub1, T3o3_stx, T3o3_swapd,
    /* Col 1 (0x10 - 0x1f) */
        T3o3_lduwa, T3o3_lduba, T3o3_lduha, T3o3_ldda,
        T3o3_stwa, T3o3_stba, T3o3_stha, T3o3_stda,
        T3o3_ldswa, T3o3_ldsba, T3o3_ldsha, T3o3_ldxa,
        T3o3_unknown_0x1c, T3o3_ldstuba, T3o3_stxa, T3o3_swapa,
    /* Col 2 (0x20 - 0x2f) */
        T3o3_ldf, T3o3_ldfsr, T3o3_ldqf, T3o3_lddf,
        T3o3_stf, T3o3_stfsr, T3o3_stqf, T3o3_stdf,
        T3o3_unknown_0x28, T3o3_unknown_0x29, T3o3_unknown_0x2a, T3o3_unknown_0x2b, 
        T3o3_unknown_0x2c, T3o3_prefetch, T3o3_unknown_0x2e, T3o3_unknown_0x2f,
    /* Col 3 (0x30 - 0x3f) */
        T3o3_ldfa, T3o3_unknown_0x31, T3o3_ldqfa, T3o3_lddfa,
        T3o3_stfa, T3o3_unknown_0x35, T3o3_stqfa, T3o3_stdfa,
        T3o3_unknown_0x38, T3o3_unknown_0x39, T3o3_unknown_0x3a, T3o3_unknown_0x3b, 
        T3o3_casa, T3o3_prefetcha, T3o3_casxa, T3o3_unknown_0x3f
} T3o3_code_t;


/*
 * Table of opf fields for the op=3, op3=0x34 floating point ops
 */

typedef enum {
        FPop34_fmovs    = 0x001,        FPop34_fmovd    = 0x002,        FPop34_fmovq    = 0x003,
        FPop34_fnegs    = 0x005,        FPop34_fnegd    = 0x006,        FPop34_fnegq    = 0x007,
        FPop34_fabss    = 0x009,        FPop34_fabsd    = 0x00a,        FPop34_fabsq    = 0x00b,
        FPop34_fsqrts   = 0x029,        FPop34_fsqrtd   = 0x02a,        FPop34_fsqrtq   = 0x02b,
        FPop34_fadds    = 0x041,        FPop34_faddd    = 0x042,        FPop34_faddq    = 0x043,
        FPop34_fsubs    = 0x045,        FPop34_fsubd    = 0x046,        FPop34_fsubq    = 0x047,
        FPop34_fmuls    = 0x049,        FPop34_fmuld    = 0x04a,        FPop34_fmulq    = 0x04b,
        FPop34_fdivs    = 0x04d,        FPop34_fdivd    = 0x04e,        FPop34_fdivq    = 0x04f,
        FPop34_fsmuld   = 0x069,        FPop34_fdmulq   = 0x06e,
        FPop34_fstox    = 0x081,        FPop34_fdtox    = 0x082,        FPop34_fqtox    = 0x083,
        FPop34_fxtos    = 0x084,        FPop34_fxtod    = 0x088,        FPop34_fxtoq    = 0x08c,
        FPop34_fitos    = 0x0c4,        FPop34_fdtos    = 0x0c6,        FPop34_fqtos    = 0x087,
        FPop34_fitod    = 0x0c8,        FPop34_fstod    = 0x0c9,        FPop34_fqtod    = 0x0cb,
        FPop34_fitoq    = 0x0cc,        FPop34_fstoq    = 0x0cd,        FPop34_fdtoq    = 0x0ce,
        FPop34_fstoi    = 0x0d1,        FPop34_fdtoi    = 0x0d2,        FPop34_fqtoi    = 0x0d3
} T3o3_fp34_opf_t;


/*
 * Table of opf fields for the op=3, op3=0x35 floating point ops
 */

typedef enum {
        FPop35_fmovrsz = 0x025, FPop35_fmovrdz = 0x026, FPop35_fmovrqz  = 0x027,
        FPop35_fmovrslez = 0x045, FPop35_fmovrdlez = 0x046, FPop35_fmovrqlez    = 0x047,
        FPop35_fmovrslz = 0x065, FPop35_fmovrdlz = 0x066, FPop35_fmovrqlz       = 0x067,
        FPop35_fmovrsnz = 0x0a5, FPop35_fmovrdnz = 0x0a6, FPop35_fmovrqnz       = 0x0a7,
        FPop35_fmovrsgz = 0x0c5, FPop35_fmovrdgz = 0x0c6, FPop35_fmovrqgz       = 0x0c7,
        FPop35_fmovrsgez = 0x0e5, FPop35_fmovrdgez = 0x0e6, FPop35_fmovrqgez    = 0x0e7,
        FPop35_fmovs_fcc0 = 0x001, FPop35_fmovd_fcc0 = 0x002, FPop35_fmovq_fcc0 = 0x003,
        FPop35_fmovs_fcc1 = 0x041, FPop35_fmovd_fcc1 = 0x042, FPop35_fmovq_fcc1 = 0x043,
        FPop35_fmovs_fcc2 = 0x081, FPop35_fmovd_fcc2 = 0x082, FPop35_fmovq_fcc2 = 0x083,
        FPop35_fmovs_fcc3 = 0x0c1, FPop35_fmovd_fcc3 = 0x0c2, FPop35_fmovq_fcc3 = 0x0c3,
        FPop35_fmovs_icc = 0x101, FPop35_fmovd_icc = 0x102, FPop35_fmovq_icc    = 0x103,
        FPop35_fmovs_xcc = 0x181, FPop35_fmovd_xcc = 0x182, FPop35_fmovq_xcc    = 0x183,
        FPop35_fcmps    = 0x051,        FPop35_fcmpd    = 0x052,        FPop35_fcmpq    = 0x053,
        FPop35_fcmpes   = 0x055,        FPop35_fcmped   = 0x056,        FPop35_fcmpeq   = 0x057
} T3o3_fp35_opf_t;


/*
 * Table of opf fields for the op=3, op3=0x36 vis ops
 */

typedef enum {
        VISop36_fzerod  = 0x060,
        VISop36_fzeros  = 0x061,        VISop36_foned   = 0x07e,        VISop36_fones   = 0x07f,
        VISop36_siam  = 0x81,
        VISop36_movdtox = 0x110, VISop36_movstouw = 0x111, VISop36_movstosw = 0x113,
        VISop36_movxtod = 0x118, VISop36_movwtos  = 0x119
} T3o3_fp36_opf_t;



typedef enum {
        Bcc_a   = 0x8,
        Bcc_n   = 0x0,
        Bcc_ne  = 0x9,
        Bcc_e   = 0x1,
        Bcc_g   = 0xA,
        Bcc_le  = 0x2,
        Bcc_ge  = 0xB,
        Bcc_l   = 0x3,
        Bcc_gu  = 0xC,
        Bcc_leu = 0x4,
        Bcc_cc  = 0xD,
        Bcc_cs  = 0x5,
        Bcc_pos = 0xE,
        Bcc_neg = 0x6,
        Bcc_vc  = 0xF,
        Bcc_vs  = 0x7
} bcc_type_t;

typedef enum {
        FBcc_a   = 0x8,
        FBcc_n   = 0x0,
        FBcc_e   = 0x9,
        FBcc_ne  = 0x1,
        FBcc_ue  = 0xA,
        FBcc_lg  = 0x2,
        FBcc_ge  = 0xB,
        FBcc_ul  = 0x3,
        FBcc_uge = 0xC,
        FBcc_l   = 0x4,
        FBcc_le  = 0xD,
        FBcc_ug  = 0x5,
        FBcc_ule = 0xE,
        FBcc_g   = 0x6,
        FBcc_o   = 0xF,
        FBcc_u   = 0x7
} fbcc_type_t;


typedef enum {
        RCond_reserved_0x0      = 0x0,
        RCond_z                 = 0x1,
        RCond_lez               = 0x2,
        RCond_lz                = 0x3,
        RCond_reserved_0x4      = 0x4,
        RCond_nz                = 0x5,
        RCond_gz                = 0x6,
        RCond_gez               = 0x7
} rcond_type_t;



#if 0   
/**/
/* Support for the condition code computation*/
/**/

#define CCODE_BIT_C     0
#define CCODE_BIT_V     1
#define CCODE_BIT_Z     2
#define CCODE_BIT_N     3

#endif  /* } */







/*
 * Support macros for the instruction decoder
 */

        /* this is for an instruction - so everything is uint32_t */
        /* verify field [_e:_s] == 0 */

#define RESERVED_FIELD(_e, _s)  ( ((((uint32_t)0xffffffff)<<((_s)+31-(_e))) >> (31-(_e))) )
#define CHECK_RESERVED_ZERO(_i, _e, _s)         \
        (( ((uint32_t)(_i)) & RESERVED_FIELD(_e, _s) ) == 0 )







#define X_OP(_i)                (((_i) >> 30) & 0x3)
#define X_OP2(_i)               (((_i) >> 22) & 0x7)
#define X_OP3(_i)               (((_i) >> 19) & 0x3f)
#define X_FMT2_FCN(_i)          (((_i) >> 25) & 0x3f)

        /* 22bit immediate for seth_i */
#define X_FMT2_IMM22(_i)                ((_i) & 0x3FFFFF)

        /* Register fields */
#define X_RS1(_i)               (((_i) >> 14) & 0x1f)
#define X_RS2(_i)               (((_i) >> 0) & 0x1f)
#define X_RD(_i)                (((_i) >> 25) & 0x1f)

        /* Immediate bit */
#define X_I(_i)                 (((_i) >> 13) & 0x1)

        /* ASI number */
#define X_ASI(_i)               (((_i) >> 5) & 0xff)

        /* Nasty set of shifting to ensure we extract sign extended correctly */
#define X_SIMM13(_i)            ((((int)(_i))<<(8*sizeof(int)-13))>>(8*sizeof(int)-13))
#define X_SIMM11(_i)            ((((int)(_i))<<(8*sizeof(int)-11))>>(8*sizeof(int)-11))
#define X_SIMM10(_i)            ((((int)(_i))<<(8*sizeof(int)-10))>>(8*sizeof(int)-10))


#define X_SHIFT_SIZE_BIT(_i)    (((_i) >> 12) & 0x1)

#define X_SHIFT_IMM32(_i)       ((_i) & 0x1f)
#define X_SHIFT_IMM64(_i)       ((_i) & 0x3f)

        /* For call instruction */
#define X_FMT1_DISP30(_i)               ((_i) & 0x3fffffff)

        /* For branches - the displacement, condition and annul bit */
#define X_FMT2_DISP22(_i)       ((_i) & 0x3FFFFF)
#define X_FMT2_DISP19(_i)       ((_i) & 0x7FFFF)
#define X_FMT2_DISP16(_i)       (((_i) & 0x3FFF) | (((_i)>>6) & 0xc000))
#define X_ANNUL_BIT(_i)         (((_i) >> 29) & 0x1)
#define X_COND(_i)              (((_i)>>25) & 0xf)
#define X_RCOND(_i)             (((_i)>>25) & 0x7)
#define X_MOVRCOND(_i)          (((_i)>>10) & 0x7)

#define X_FMT3_RCOND(_i)        (((_i) >> 10) & 0x7)

#define X_FMT2_CC(_i)           (((_i) >>20) & 0x3)
typedef enum {
        CC2bit_icc      = 0x0,
        CC2bit_xcc      = 0x2
} cc2bit_t;

typedef enum {
        FCC2bit_fcc0    = 0x0,
        FCC2bit_fcc1    = 0x1,
        FCC2bit_fcc2    = 0x2,
        FCC2bit_fcc3    = 0x3
} fcc2bit_t;

#define X_FMT4_CC(_i)           (((_i) >>11) & 0x3)
typedef enum {
        CC4bit_icc      = 0x0,
        CC4bit_xcc      = 0x2
} cc4bit_t;

        /* For the conditional move instructions */

#define X_FMT4_CC2(_i)          (((_i)>>18)&1)  /* =0 if FPCC =1 if ICC */
#define X_FMT4_CC2a(_i)         (((_i)>>13)&1)  /* =0 if FPCC =1 if ICC */
#define X_FMT4_COND(_i)         (((_i)>>14)&0xf)

#define X_MEMBAR_MASKS(_i)      ((_i) & 0x7f)



        /* Format 3 - done and retry instructions */

#define FMT3_FCN_SHIFT          25
#define FMT3_FCN_MASK_BITS      5
#define FMT3_FCN_MASK_BASE      ((1LL<<FMT3_FCN_MASK_BITS)-1)
#define X_FMT3_FCN(_i)          (((_i)>>FMT3_FCN_SHIFT)&FMT3_FCN_MASK_BASE)



        /*
         * Floating point instructions
         */

#define FMT3_FP_OPF_SHIFT       5
#define FMT3_FP_OPF_MASK        0x1ff
#define X_FP_OPF( _i )          (((_i)>>FMT3_FP_OPF_SHIFT)&FMT3_FP_OPF_MASK)
#define X_FCOND(_i)             (((_i)>>25) & 0x3)

/* rescale reg num for fp double regs */
#define RESCALEFPREG(_R)        (_R) = ((_R) & 0x1e) | (((_R) & 1)<<5)

        /*
         * setup for the xicache processing
         */

#define SET_OP(_n)      do { exec_funcp = decoded_impl_##_n ; } while (0)
#define SET_OPv9(_n)    do { exec_funcp = decoded_impl_sparcv9_##_n ; } while (0)

#ifdef  __cplusplus
}
#endif

#endif /* _SPARCV9DECODE_H_ */